package com.cutefool.zero.code.admin.meta.column.service;

import com.cutefool.core.kits.consts.Status;
import com.cutefool.core.res.Message;
import com.cutefool.core.res.Response;
import com.cutefool.core.res.ResponseCode;
import com.cutefool.dsl.mybatis.core.dsl.builder.InsertDsl;
import com.cutefool.dsl.mybatis.core.dsl.builder.QueryDsl;
import com.cutefool.dsl.mybatis.core.dsl.operation.CuteCurdOperation;
import com.cutefool.rds.enums.RdsFieldType;
import com.cutefool.zero.code.admin.meta.column.dto.ColumnDTO;
import com.cutefool.zero.code.admin.meta.column.support.ColumnDbSupport;
import com.cutefool.zero.code.core.domain.ModelColumn;
import com.cutefool.zero.code.core.domain.ModelColumnOption;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.dynamic.sql.SqlBuilder;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;
import java.util.Optional;

@Component
public class ColumnService {

    @Resource
    private ColumnDbSupport columnDbSupport;

    @Resource
    private CuteCurdOperation<ModelColumn> cuteCurdOperation;

    @Resource
    private CuteCurdOperation<ModelColumnOption> columnOptionCuteCurdOperation;


    @Transactional(rollbackFor = RuntimeException.class)
    public Response<Boolean> create(ColumnDTO dto) {
        Response<Boolean> validate = this.validate(null, dto);
        if (validate.isFailure()) {
            return validate;
        }
        InsertDsl<ModelColumn> insertDsl = InsertDsl.newInstance(ModelColumn.instance()).entity(dto, (d, s) -> {
            Byte nullable = s.getNullable();
            d.setNullable(Objects.isNull(nullable) ? Status.STATUS_FALSE : Status.STATUS_TRUE);
            Byte isUnique = s.getIsUnique();
            d.setIsUnique(Objects.isNull(isUnique) ? Status.STATUS_FALSE : Status.STATUS_TRUE);
            Byte isSearch = s.getIsSearch();
            d.setIsSearch(Objects.isNull(isSearch) ? Status.STATUS_FALSE : Status.STATUS_TRUE);
            Byte isDefault = s.getIsDefault();
            d.setIsDefault(Objects.isNull(isDefault) ? Status.STATUS_FALSE : Status.STATUS_TRUE);
            d.setIsSync(Status.STATUS_FALSE);
            // 长度处理
            RdsFieldType rdsFieldType = RdsFieldType.valueOf(s.getType());
            Integer len = s.getLen();
            d.setLen(Objects.isNull(len) ? rdsFieldType.getLen() : len);
            Integer scale = s.getScale();
            d.setScale(Objects.isNull(scale) ? rdsFieldType.getScale() : scale);
        });
        this.cuteCurdOperation.create(insertDsl);
        String options = dto.getOptions();
        if (StringUtils.isNotBlank(options)) {
            ModelColumnOption option = new ModelColumnOption();
            option.setOption(options);
            ModelColumn entity = insertDsl.getEntity();
            option.setColumnId(entity.getId());
            option.setAppId(entity.getAppId());
            option.setCompanyId(entity.getCompanyId());
            option.setModelId(entity.getModelId());
            option.setDbmsId(entity.getDbmsId());
            InsertDsl<ModelColumnOption> insertOptionDsl = InsertDsl.newInstance(ModelColumnOption.instance()).entity(option);
            // 保存配置项
            columnOptionCuteCurdOperation.create(insertOptionDsl);
        }
        // 同步到数据库
        columnDbSupport.doSyncToDb(insertDsl.getEntity());
        return Response.ok();
    }


    public Response<Boolean> validate(Long id, ColumnDTO dto) {
        boolean validateName = this.validateName(id, dto.getTableName(), dto.getName());
        if (!validateName) {
            return Response.failure(ResponseCode.API_ERROR.getCode(), String.format(Message.MESSAGE_DATA_EXISTS, dto.getName()));
        }
        boolean validateTableName = this.validateDisplayName(id, dto.getTableName(), dto.getDisplayName());

        if (!validateTableName) {
            return Response.failure(ResponseCode.API_ERROR.getCode(), String.format(Message.MESSAGE_DATA_EXISTS, dto.getDisplayName()));
        }
        return Response.ok();
    }


    public boolean validateName(Long id, String tableName, String name) {
        ModelColumn instance = ModelColumn.instance();
        QueryDsl<ModelColumn> queryDsl = QueryDsl.newInstance(instance, where -> {
            where.and(instance.table().name, SqlBuilder.isEqualTo(name));
            where.and(instance.table().tableName, SqlBuilder.isEqualTo(tableName));
        });

        Optional<ModelColumn> optional = cuteCurdOperation.get(queryDsl);
        return optional.isEmpty() || optional.filter(e -> Objects.equals(e.getId(), id)).stream().findAny().isPresent();


    }

    public boolean validateDisplayName(Long id, String tableName, String displayNam) {
        ModelColumn instance = ModelColumn.instance();
        QueryDsl<ModelColumn> queryDsl = QueryDsl.newInstance(instance, where -> {
            where.and(instance.table().displayName, SqlBuilder.isEqualTo(displayNam));
            where.and(instance.table().tableName, SqlBuilder.isEqualTo(tableName));
        });
        Optional<ModelColumn> optional = cuteCurdOperation.get(queryDsl);
        return optional.isEmpty() || optional.filter(e -> Objects.equals(e.getId(), id)).stream().findAny().isPresent();
    }
}
